﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace eventModel
{
    /// <summary>This class is used to process a file before it is passed on to the compiler.</summary>
    static class Parser
    {
        // Get our base C# script container and load it into memory:
        private static string ScriptHeader = eventModel.Properties.Resources.ScriptHeader;

        /// <summary>This class is used to store in memory the language tokens and definitions.</summary>
        private class Syntax
        {
            public static string OpnTkn { get { return "@{"; } }
            public static string ClsTkn { get { return "}@"; } }
            public static string HTMLOpener { get { return "\nResponce.Append(@\""; } }
            public static string HTMLClose { get { return "\");\n"; } }
        }

        /// <summary>Pre-processed a script file and returns code ready for compilation.</summary>
        /// <param name="filename">Script File Name</param>
        public static string Process(string filename)
        {
            // Read contents from script file first:
            string filContents = File.ReadAllText(filename);

            // Look for opening tags:
            while (filContents.Contains(Syntax.OpnTkn))
            {
                // If there are opening tags make sure there are closing tags as well:
                if (filContents.Contains(Syntax.ClsTkn))
                {
                    // Text always starts out as "HTML", so begin write statement:
                    filContents = filContents.Insert(0, Syntax.HTMLOpener);
                    int CrntIndx = Syntax.HTMLOpener.Length;

                    // Find next open token and clean the data in between:
                    int indxOpn = filContents.IndexOf(Syntax.OpnTkn);
                    string unescapedHTML = filContents.Substring(CrntIndx,indxOpn-CrntIndx);
                    // Remove old html data and open token:
                    filContents = filContents.Remove(CrntIndx, unescapedHTML.Length + Syntax.ClsTkn.Length);
                    //Insert new clean data and complete write statement:
                    filContents = filContents.Insert(CrntIndx, unescapedHTML.Replace("\"", "\"\"") + Syntax.HTMLClose);

                    // Find next close token, remove it, and assume we begin HTML again (begin write statement):
                    indxOpn = filContents.IndexOf(Syntax.ClsTkn);
                    filContents = filContents.Remove(indxOpn,2);
                    filContents = filContents.Insert(indxOpn, Syntax.HTMLOpener);

                }
                else 
                { 
                    //if there are no closing tags we have an error:
                    Logging.Add("Error parsing script '" + filename + "'. (Incorrect opening/closing tags?)");
                    throw new Exception("Opening tag '"+Syntax.OpnTkn+"' on line is missing closing tag '"+Syntax.ClsTkn+"'");
                }

                //Close HTML write statement
                filContents += Syntax.HTMLClose; 
            }

            //Take template, insert parsed code, and return result:
            return ScriptHeader.Replace("//%script%", filContents);
        }
    }
}
